#include <linux/shm.h>


static shm_ds shm_list[shm_ds_size] = { {0,0,0} };

//创建共享内存
int sys_shmget(key_t key, size_t size, int shmflg)
{
    int i;
    unsigned long page;
    int shmid = -1;

    if (!key)
    {
        printk("key is 0!\n");
        errno = EINVAL;
        return -1;
    }

    if (size > PAGE_SIZE)
    {
        printk("size is larger then a page!\n");//太大了
        errno = EINVAL;
        return -1;
    }

    for (i = 0;i < shm_ds_size;i++)
    {
        if (shm_list[i].key == key)return i;   //判断是否是存在的存在则返回索引
        else if (shm_list[i].key == 0 && shmid == -1)shmid = i;
    }

    if (shmid >= 0)
    {

        page = get_free_page();
        if (!page)
        {
            errno = ENOMEM;
            printk("memory is full!\n");
            return -1;
        }

        shm_list[shmid].key = key;
        shm_list[shmid].page = page;
        shm_list[shmid].size = size;
    }
   // printk("shmid:%d\n",shmid);
    return shmid;
}

//挂载共享内存
void* sys_shmmat(int shmid, const void* shmaddr, int shmflg)
{

    int i;
    unsigned long database;
    
    if (shm_list[shmid].key == 0 || shmid > shm_ds_size||shmid<0||shm_list[shmid].page==0)
    {
        errno = EINVAL;
        printk("shmid is errno!\n");
        return NULL;
    }

    if(put_page(shm_list[shmid].page,current->start_code+current->brk)==0)//虚拟地址与物理地址形成映射
    {
        return NULL;
    }

    current->brk += PAGE_SIZE;//更新当前线程的brk 使用了一页的虚拟内存

    return (void *)(current->brk-PAGE_SIZE);//返回当前进程的偏移地址   
}


//释放共享内存
int sys_shmctl(int shmid)
{
   if (shm_list[shmid].key == 0 || shmid > shm_ds_size||shmid<0||shm_list[shmid].page==0)
    {
        printk("shmid is errno!\n");
        return 0;
    }
    shm_list[shmid].key=0;
    shm_list[shmid].size=0;
    free_page(shm_list[shmid].page);
    shm_list[shmid].page=0;
    current->brk -=PAGE_SIZE;
    return 1;
}

